home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Direct3D / DepthOfField / DepthOfField.fx < prev    next >
Encoding:
Text File  |  2004-09-27  |  15.3 KB  |  418 lines

  1. //-----------------------------------------------------------------------------
  2. // File: DepthOfField.fx
  3. //
  4. // Desc: Effect file for depth of field blur. The HLSL shaders are used 
  5. //       calculate the depth of each vertex and this information is stored in the 
  6. //       vertex diffuse alpha channel.  A post process pixel shader is
  7. //       then used to blur the scene based on the render target's alpha value.
  8. // 
  9. // Copyright (c) Microsoft Corporation. All rights reserved.
  10. //-----------------------------------------------------------------------------
  11.  
  12.  
  13. //-----------------------------------------------------------------------------
  14. // Global variables
  15. //-----------------------------------------------------------------------------
  16. float4 MaterialAmbientColor;
  17. float4 MaterialDiffuseColor;
  18.  
  19. float3 LightDir = normalize(float3(1.0f, 1.0f, -1.0f));
  20. float4 LightAmbient = { 1.0f, 1.0f, 1.0f, 1.0f };    // ambient
  21. float4 LightDiffuse = { 1.0f, 1.0f, 1.0f, 1.0f };    // diffuse
  22.  
  23. texture RenderTargetTexture;
  24. texture MeshTexture;
  25.  
  26. float4x4 mWorld;
  27. float4x4 mWorldView;
  28. float4x4 mWorldViewProjection;
  29.  
  30. float4 vFocalPlane;
  31. float  fHyperfocalDistance = 0.4f;
  32. float  MaxBlurFactor = 3.0f / 4.0f;
  33.  
  34. // This array defines the blur pattern to be used in the 
  35. // post process pixel shaders.  It is two hexagons, one a single pixel 
  36. // out and the other two pixels out with close to "equal" spacing between 
  37. // the points in order to get the best blurring.
  38. float2 TwelveKernelBase[12] =
  39. {
  40.     { 1.0f,  0.0f},
  41.     { 0.5f,  0.8660f},
  42.     {-0.5f,  0.8660f},
  43.     {-1.0f,  0.0f},
  44.     {-0.5f, -0.8660f},
  45.     { 0.5f, -0.8660f},
  46.     
  47.     { 1.5f,  0.8660f},
  48.     { 0.0f,  1.7320f},
  49.     {-1.5f,  0.8660f},
  50.     {-1.5f, -0.8660f},
  51.     { 0.0f, -1.7320f},
  52.     { 1.5f, -0.8660f},
  53. };
  54.  
  55. // This array is filled in by the app by scaling the above array by
  56. // the backbuffer dimensions to convert the numbers from 
  57. // pixel space to screen space 
  58. float2 TwelveKernel[12];
  59.  
  60.  
  61. //-----------------------------------------------------------------------------
  62. // Texture samplers
  63. //-----------------------------------------------------------------------------
  64. sampler RenderTargetSampler = 
  65. sampler_state
  66. {
  67.     Texture = <RenderTargetTexture>;
  68.     MinFilter = LINEAR;
  69.     MagFilter = LINEAR;
  70.  
  71.     AddressU = Clamp;
  72.     AddressV = Clamp;
  73. };
  74.  
  75. sampler MeshTextureSampler = 
  76. sampler_state
  77. {
  78.     Texture = <MeshTexture>;
  79.     MinFilter = LINEAR;
  80.     MagFilter = LINEAR;
  81.     MipFilter = LINEAR;
  82. };
  83.  
  84.  
  85. //-----------------------------------------------------------------------------
  86. // Vertex shader output structure
  87. //-----------------------------------------------------------------------------
  88. struct VS_OUTPUT
  89. {
  90.     float4 Position : POSITION;
  91.     float4 Diffuse : COLOR;
  92.     float2 TextureUV : TEXCOORD0;
  93. };
  94.  
  95.  
  96. //-----------------------------------------------------------------------------
  97. // Name: WorldVertexShader
  98. // Type: Vertex shader                                      
  99. // Desc: In addition to standard transform and lighting, it calculates the blur
  100. //       factor of the vertex and outputs this as a texture coord.
  101. //-----------------------------------------------------------------------------
  102. VS_OUTPUT WorldVertexShader( float4 vPos : POSITION, 
  103.                              float3 vNormal : NORMAL,
  104.                              float2 vTexCoord0 : TEXCOORD0 )
  105. {
  106.     VS_OUTPUT Output;
  107.     float3 vViewPosition;
  108.     float3 vWorldNormal;
  109.     float  fBlurFactor;
  110.   
  111.     // tranform vertex position into screen space
  112.     Output.Position = mul(vPos, mWorldViewProjection);
  113.     
  114.     // tranform vertex position into view space
  115.     vViewPosition = mul(vPos, (float4x3)mWorldView);
  116.     
  117.     // tranform vertex normal into world space
  118.     vWorldNormal = mul(vNormal, (float3x3)mWorld);       
  119.     
  120.     // Compute simple lighting equation
  121.     Output.Diffuse.rgb = MaterialDiffuseColor * LightDiffuse * max(0,dot(vWorldNormal, LightDir)) + 
  122.                          MaterialAmbientColor * LightAmbient;
  123.     
  124.     // Compute blur factor and place in output alpha
  125.     fBlurFactor      = dot(float4(vViewPosition, 1.0), vFocalPlane)*fHyperfocalDistance;
  126.     Output.Diffuse.a = fBlurFactor*fBlurFactor;
  127.     
  128.     // Put a cap on the max blur value.  This is required to ensure that the center pixel
  129.     // is always weighted in the blurred image.  I.E. in the PS11 case, the correct maximum
  130.     // value is (NumSamples - 1) / NumSamples, otherwise at BlurFactor == 1.0f, only the outer
  131.     // samples are contributing to the blurred image which causes annoying ring artifacts
  132.     Output.Diffuse.a = min(Output.Diffuse.a, MaxBlurFactor);
  133.     
  134.     // Just copy the texture coordinate through
  135.     Output.TextureUV = vTexCoord0;
  136.     
  137.     return Output;    
  138. }
  139.  
  140.  
  141. //-----------------------------------------------------------------------------
  142. // Name: WorldPixelShader
  143. // Type: Pixel shader
  144. // Desc: This shader simply outputs the pixel's color 
  145. //-----------------------------------------------------------------------------
  146. float4 WorldPixelShader( VS_OUTPUT In ) : COLOR
  147.     // Lookup mesh texture and modulate it with the diffuse color
  148.     return tex2D(MeshTextureSampler, In.TextureUV) * In.Diffuse;
  149. }
  150.  
  151.  
  152. //-----------------------------------------------------------------------------
  153. // Name: DepthOfFieldFourTexcoords
  154. // Type: Pixel shader
  155. // Desc: This post process pixel shader uses four texcoords to lookup into the 
  156. //       render-target texture to blur the image based on the value of alpha channel.
  157. //       Note: Setting bWithRings to false looks better but for demonstration purposes
  158. //       the technique "UsePS11FourTexcoordsWithRings" which sets it to false
  159. //-----------------------------------------------------------------------------
  160. float4 DepthOfFieldFourTexcoords( in float2 OriginalUV : TEXCOORD0,
  161.                                   in float2 JitterUV[3] : TEXCOORD1, 
  162.                                   uniform bool bWithRings ) : COLOR
  163. {    
  164.     float4 Original = tex2D(RenderTargetSampler, OriginalUV);
  165.     float4 Jitter[3];
  166.     float3 Blurred;
  167.     
  168.     for(int i = 0; i < 3; i++)
  169.     {
  170.         // Lookup into the rendertarget based on a texture coord.
  171.         // See app's SetupQuad() to see how the texture coords are created 
  172.         Jitter[i] = tex2D(RenderTargetSampler, JitterUV[i]);
  173.         
  174.         // Lerp between original rgb and the jitter rgb based on the alpha value
  175.         if( bWithRings )
  176.             Jitter[i].rgb = lerp(Original.rgb, Jitter[i].rgb, Original.a);
  177.         else
  178.             Jitter[i].rgb = lerp(Original.rgb, Jitter[i].rgb, saturate(Original.a*Jitter[i].a));
  179.     }
  180.         
  181.     // Average the first two jitter samples
  182.     Blurred = lerp(Jitter[0].rgb, Jitter[1].rgb, 0.5);
  183.     
  184.     // Equally weight all three jitter samples
  185.     Blurred = lerp(Jitter[2].rgb, Blurred, 0.66666);
  186.     
  187.     return float4(Blurred, 1.0f);
  188. }
  189.  
  190.  
  191. //-----------------------------------------------------------------------------
  192. // Name: DepthOfFieldWithSixTexcoords
  193. // Type: Pixel shader
  194. // Desc: This post process pixel shader uses six texcoords to lookup into the 
  195. //       render-target texture to blur the image based on the value of alpha channel.
  196. //-----------------------------------------------------------------------------
  197. float4 DepthOfFieldWithSixTexcoords( in float2 OriginalUV : TEXCOORD0,
  198.                                      in float2 JitterUV[5] : TEXCOORD1 ) : COLOR
  199. {
  200.     float4 Original = tex2D(RenderTargetSampler, OriginalUV);
  201.     float4 Jitter[5];
  202.     float3 Blurred = 0;
  203.     
  204.     for(int i = 0; i < 5; i++)
  205.     {
  206.         // Lookup into the rendertarget based on a texture coord.
  207.         // See app's SetupQuad() to see how the texture coords are created 
  208.         Jitter[i] = tex2D(RenderTargetSampler, JitterUV[i]);
  209.         
  210.         // Lerp between original rgb and the jitter rgb based on the alpha value
  211.         Blurred += lerp(Original.rgb, Jitter[i].rgb, saturate(Original.a*Jitter[i].a));
  212.     }
  213.             
  214.     return float4(Blurred / 5.0f, 1.0f);
  215. }
  216.  
  217.  
  218. //-----------------------------------------------------------------------------
  219. // Name: DepthOfFieldManySamples
  220. // Type: Pixel shader
  221. // Desc: This post process pixel shader uses an array of values to offset into the 
  222. //       render-target texture to blur the image based on the value of alpha channel.
  223. //-----------------------------------------------------------------------------
  224. float4 DepthOfFieldManySamples( in float2 OriginalUV : TEXCOORD0,
  225.                                 uniform float2 KernelArray[12],
  226.                                 uniform int NumSamples ) : COLOR
  227. {
  228.     float4 Original = tex2D(RenderTargetSampler, OriginalUV);
  229.     float3 Blurred = 0;
  230.     
  231.     for(int i = 0; i < NumSamples; i++)
  232.     {
  233.         // Lookup into the rendertarget based by offsetting the 
  234.         // original UV by KernelArray[i].  See the TwelveKernelBase[] above
  235.         // and UpdateTechniqueSpecificVariables() for how this array is created
  236.         float4 Current = tex2D(RenderTargetSampler, OriginalUV + KernelArray[i]);
  237.         
  238.         // Lerp between original rgb and the jitter rgb based on the alpha value
  239.         Blurred += lerp(Original.rgb, Current.rgb, saturate(Original.a*Current.a));
  240.     }
  241.             
  242.     return float4(Blurred / NumSamples, 1.0f);
  243. }
  244.  
  245.  
  246. //-----------------------------------------------------------------------------
  247. // Name: RenderBlurFactor
  248. // Type: Pixel shader
  249. // Desc: Outputs the blur factor as the pixel's color.  The blur factor is 
  250. //       stored in the alpha channel
  251. //-----------------------------------------------------------------------------
  252. float4 RenderBlurFactor( in float2 OriginalUV : TEXCOORD0 ) : COLOR 
  253. {
  254.     float4 Original = tex2D(RenderTargetSampler, OriginalUV);
  255.     return (1-Original.a); // Invert so the screen isn't pure white
  256. }
  257.  
  258.  
  259. //-----------------------------------------------------------------------------
  260. // Name: RenderUnmodified
  261. // Type: Pixel shader
  262. // Desc: Outputs the original pixel's color without bluring
  263. //-----------------------------------------------------------------------------
  264. float4 RenderUnmodified( in float2 OriginalUV : TEXCOORD0 ) : COLOR 
  265. {
  266.     return tex2D(RenderTargetSampler, OriginalUV);
  267. }
  268.  
  269.  
  270. //-----------------------------------------------------------------------------
  271. // Name: WorldWithBlurFactor
  272. // Type: Technique                                     
  273. // Desc: Renders the scene's color to the render target and stores the
  274. //       depth information as a blur factor in the alpha channel.
  275. //-----------------------------------------------------------------------------
  276. technique WorldWithBlurFactor
  277. {
  278.     pass P0
  279.     {        
  280.         VertexShader = compile vs_1_1 WorldVertexShader();
  281.         PixelShader  = compile ps_1_1 WorldPixelShader();
  282.     }
  283. }
  284.  
  285.  
  286. //-----------------------------------------------------------------------------
  287. // Name: UsePS20ThirteenLookups
  288. // Type: Technique                                     
  289. // Desc: This post-process technique uses an array of 12 values to offset into the 
  290. //       render-target texture to blur the image based on the value of alpha 
  291. //       channel.  It performs a total of 13 texture lookups
  292. //-----------------------------------------------------------------------------
  293. technique UsePS20ThirteenLookups
  294. <
  295.     float MaxBlurFactor = 12.0f / 13.0f;
  296.     int NumKernelEntries = 12;
  297.     string KernelInputArray = "TwelveKernelBase";
  298.     string KernelOutputArray = "TwelveKernel";  
  299. >
  300. {
  301.     pass P0
  302.     {        
  303.         PixelShader = compile ps_2_0 DepthOfFieldManySamples(TwelveKernel, 12);
  304.     }
  305. }
  306.  
  307.  
  308. //-----------------------------------------------------------------------------
  309. // Name: UsePS20SevenLookups
  310. // Type: Technique                                     
  311. // Desc: This post-process technique uses an array of 6 values to offset into the 
  312. //       render-target texture to blur the image based on the value of alpha 
  313. //       channel.  It performs a total of 7 texture lookups
  314. //-----------------------------------------------------------------------------
  315. technique UsePS20SevenLookups
  316. <
  317.     float MaxBlurFactor = 6.0f / 7.0f;
  318.     int NumKernelEntries = 12;
  319.     string KernelInputArray = "TwelveKernelBase";
  320.     string KernelOutputArray = "TwelveKernel";  
  321. >
  322. {
  323.     pass P0
  324.     {        
  325.         PixelShader = compile ps_2_0 DepthOfFieldManySamples(TwelveKernel, 6);
  326.     }
  327. }
  328.  
  329.  
  330. //-----------------------------------------------------------------------------
  331. // Name: UsePS20SixTexcoords
  332. // Type: Technique                                     
  333. // Desc: This post-process technique uses six texcoords to lookup into the 
  334. //       render-target texture to blur the image based on the value of alpha 
  335. //       channel. It performs a total of 6 texture lookups
  336. //-----------------------------------------------------------------------------
  337. technique UsePS20SixTexcoords
  338. <
  339.     float MaxBlurFactor = 4.0f / 5.0f;
  340. >
  341. {
  342.     pass P0
  343.     {        
  344.         PixelShader = compile ps_2_0 DepthOfFieldWithSixTexcoords();
  345.     }
  346. }
  347.  
  348.  
  349. //-----------------------------------------------------------------------------
  350. // Name: UsePS11FourTexcoordsNoRings
  351. // Type: Technique                                     
  352. // Desc: This post-process technique technique uses four texcoords to lookup into 
  353. //       the render-target texture to blur the image based on the value of alpha 
  354. //       channel. It performs a total of 4 texture lookups
  355. //-----------------------------------------------------------------------------
  356. technique UsePS11FourTexcoordsNoRings
  357. <
  358.     float MaxBlurFactor = 3.0f / 4.0f;
  359. >
  360. {
  361.     pass P0
  362.     {        
  363.         PixelShader = compile ps_1_1 DepthOfFieldFourTexcoords( false );
  364.     }
  365. }
  366.  
  367.  
  368. //-----------------------------------------------------------------------------
  369. // Name: UsePS11FourTexcoordsWithRings
  370. // Type: Technique                                     
  371. // Desc: This post-process technique uses four texcoords to lookup into the render-target 
  372. //       texture to blur the image based on the value of alpha channel.
  373. //       The technique "UsePS11FourTexcoordsNoRings" looks better but for 
  374. //       demonstration purposes this technique shows what this looks like 
  375. //-----------------------------------------------------------------------------
  376. technique UsePS11FourTexcoordsWithRings
  377. <
  378.     float MaxBlurFactor = 3.0f / 4.0f;
  379. >
  380. {
  381.     pass P0
  382.     {        
  383.         PixelShader = compile ps_1_1 DepthOfFieldFourTexcoords( true );
  384.     }
  385. }
  386.  
  387.  
  388. //-----------------------------------------------------------------------------
  389. // Name: ShowBlurFactor
  390. // Type: Technique                                     
  391. // Desc: A post-process technique to display the per pixel blur factor 
  392. //       which is stored in the alpha channel
  393. //-----------------------------------------------------------------------------
  394. technique ShowBlurFactor
  395. {
  396.     pass P0
  397.     {        
  398.         PixelShader = compile ps_1_1 RenderBlurFactor();
  399.     }
  400. }
  401.  
  402.  
  403. //-----------------------------------------------------------------------------
  404. // Name: ShowUnmodified
  405. // Type: Technique
  406. // Desc: A post-process technique to display the original unblurred image
  407. //-----------------------------------------------------------------------------
  408. technique ShowUnmodified
  409. {
  410.     pass P0
  411.     {        
  412.         PixelShader = compile ps_1_1 RenderUnmodified();
  413.     }
  414. }
  415.  
  416.  
  417.